// -----------------------------------------------------------------
//                      Team D
//                      Members:
//                            Ian Bell
//                            Art Ordonez
//                            Stephen Rippon
//                            Jason Vance
//                            Brent Wilkerson
//                      CS 4280 TTH 11:30am
//                      Team Assignment #5
//                      Dr. Rague
//                      Due: 8 Nov 2012
//                      Version: 1.0
// -----------------------------------------------------------------
//		This is an OpenGL program that renders a scene of objects in
//		a three dimensional space. Among rendering of an assortment
//		of objects, there is also a camera object that allows the user
//		to fly around the scene.
// -----------------------------------------------------------------
// -----------------------------------------------------------------
//	Change Control Section
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: <0.1
//		Date:  31 Oct 2012
//		Created a couple of static and animated 3D objects for the
//		scene and a renderer to display and switch between them.
// -----------------------------------------------------------------
//		Team Member:  Brent Wilkerson
//		Version: <0.1
//		Date:  1 Nov 2012
//		Created the default camera and controls to view a basic
//		scene containing a teapot.
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: <0.1
//		Date:  31 Oct 2012
//		Added GrassField, GrassPatch, and animated GrassBlade objects.
// -----------------------------------------------------------------
//		Team Member:  Stephen Rippon
//		Version: 0.2
//		Date:  5 Nov 2012
//		Merged Brent's and Jason's code into one project.
//		Added a delta to keep animations consistent regardless of FPS.
//		Added a basic FPS counter that outputs to the console.
//		Added a basic heightmap terrain, needs work.
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: 0.3
//		Date:  6 Nov 2012
//		Updated GrassPatch in particular and other grass related
//		things. Greatly increases performance.
// -----------------------------------------------------------------
//		Team Member:  Stephen Rippon
//		Version: 0.4
//		Date:  6 Nov 2012
//		Fixed potential issues with FPS display, slightly modified
//		grass color, added skeleton code for better control handling.
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: 0.5
//		Date:  7 Nov 2012
//		Added calculation of normals to House.h, WindMill.h, and 
//		PineTree.h. I also partially implemented the ability to 
//		define a GrassPatch by using four points.
// -----------------------------------------------------------------
//		Team Member:  Stephen Rippon
//		Version: 0.6
//		Date:  7 Nov 2012
//		Made keyboard controls more responsive and smoother, minor adjustments
//		to the grass LOD calculations, slightly reduced amount of grass.
//		Made grass on sloped GrassPatches have the correct height.
// -----------------------------------------------------------------
//		Team Member:  Stephen Rippon
//		Version: 0.7
//		Date:  8 Nov 2012
//		Pre-presentation scramble!
//		Camera movement now affected by delta, heightmap now consists
//		of GrassPatches, attempted to get normals working on the terrain, 
//		removed the object changer/presentor, and lots of misc. bugfixes.
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: 0.8
//		Date:  8 Nov 2012
//		Placed various 3D objects on the terrain. Added the ability
//		to change the viewing angle and the aspect ratio.  Also
//		updated the controls to printInstructions() in Controls.cpp.
// -----------------------------------------------------------------
#include <windows.h>
#include <gl/Gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <math.h>
#include <iostream>
#include <time.h>

#include "Camera.h"
#include "WorldSector.h"
#include "House.h"
#include "WindMill.h"
#include "PineTree.h"

using namespace std;

// Global Variables
float lod = 10.0;
float lodDecay = 5.0;

// Global Objects
Camera cam = Camera();
WorldSector terrain = WorldSector(0, 0);
vector<Object*> objects;

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	terrain.draw();
	for (unsigned int i=0;i<objects.size();i++) {
		objects[i]->draw();
	}

	glutSwapBuffers();
}

void updateControls(float delta);  // Defined in controls.cpp
int lastFrame = 0;
void doIdle()
{
	// Calculate Delta
	int curFrame = glutGet(GLUT_ELAPSED_TIME);
	float delta = (curFrame - lastFrame) / (float)1000;
	lastFrame = curFrame;

	// Output FPS
	cout << 1/delta << "               \r"; 

	// Update objects and controls
	updateControls(delta);
	terrain.update(delta);
	for (unsigned int i=0;i<objects.size();i++) {
		objects[i]->update(delta);
	}
	
	glutPostRedisplay();
}

void createObjects() {
	// Set up the objects

	// House
	objects.push_back(new House(0, 0, 0, 5, 45));

	// Windmill
	objects.push_back(new WindMill(2, 0, 2, 5, 1.0f));

	//Pine Trees
	objects.push_back(new PineTree(1, 0, 1, 5));
	objects.push_back(new PineTree(6, 0, 4, 5));
	objects.push_back(new PineTree(1, 0, 3, 5));
	objects.push_back(new PineTree(5, 0, 5, 5));
	objects.push_back(new PineTree(5, 0, 1, 5));
}


void init()
{
	glClearColor(0.2, 0.4, 0.8, 1.0);
	glColor3f(0.0, 0.0, 0.0);
	glMatrixMode(GL_PROJECTION);

	cam.setView(30.0, 1.0, 0.1, 50.0);
	cam.setCamera(Vector3(3,2,15),Vector3(1,0,0),Vector3(0,1,0),Vector3(0,0,1));

	// Set up the shading
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST); // for hidden surface removal
	glEnable(GL_NORMALIZE); // normalize Vector2Ds for proper shading

	//// set the light source properties
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
	GLfloat light_diffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
	GLfloat light_ambient[] = {0.5f, 0.5f, 0.5f, 1.0f};
	GLfloat light_position[] = {3.0f, 4.0f, 3.0f, 0.0f};
	glLightfv(GL_LIGHT0, GL_POSITION, light_position);
	glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
}


// Callbacks from controls.cpp
void doKeyUp(unsigned char key, int x, int y);
void doKeyboard(unsigned char key, int x, int y);
void doMouse(int button, int state, int x, int y);
void doMotion(int x, int y);
void printInstructions();

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowSize(800, 800);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("Team D - Assignment 5: The Grassy Knoll");

	glutDisplayFunc(display);
	glutIdleFunc(doIdle);

	//Control callbacks
	glutKeyboardUpFunc(doKeyUp);
	glutKeyboardFunc(doKeyboard);
	glutMouseFunc(doMouse);
	glutMotionFunc(doMotion);

	init();
	createObjects();

	printInstructions();
	cout << "\nFPS:\n";

	glutMainLoop();
}